﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using DevComponents.DotNetBar;
using Matrix_ClassLibrary;

namespace LTTT_Client
{
    public partial class Receiver : DevComponents.DotNetBar.Office2007Form
    {
        public  delegate void InvokeSomeMethod();
        Matrix matrix=null;
        Matrix TestingMatrix=null;
        ConnectionClient connect;

        public Receiver()
        {
            InitializeComponent();
        }

        // Hàm cài đặt các quá trình sau khi nhận được ma trận
        private void PopulateMatrix()
        {
            // nhận ma trận
            this.matrix = connect.matrix;
            //Cài đặt Datagridview hiển thị
            SetupDataGridView(matrix);
            // Tạo ma trận kiểm tra
            this.TestingMatrix = matrix.MakeTestingMatrix();
            
        }

        // Hàm cài đặt, cấu hình datagridview để hiển thì ma trận
        private void SetupDataGridView(Matrix matrix)
        {
            dgvMatrix.Rows.Clear();
            dgvMatrix.Columns.Clear();
            DataGridViewTextBoxColumn boxcolumn;
            DataGridViewCellStyle cellStyle;
            for (int i = 0; i < matrix.column; i++)
            {
                boxcolumn = new DataGridViewTextBoxColumn();
                cellStyle = new DataGridViewCellStyle();
                if (i % 2 == 1)
                {
                    cellStyle.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(255)))), ((int)(((byte)(192)))));
                    boxcolumn.DefaultCellStyle = cellStyle;

                }
                boxcolumn.HeaderText = "a" + (i + 1).ToString();
                boxcolumn.Width = dgvMatrix.Width / matrix.column;
                dgvMatrix.Columns.Add(boxcolumn);

            }

            //Bỏ chức năng sort column của datagridview
            foreach (DataGridViewColumn col in dgvMatrix.Columns)
            {
                col.SortMode = DataGridViewColumnSortMode.NotSortable;
            }
            string[] arrInt = new string[matrix.column];
            for (int i = 0; i < matrix.row; i++)
            {
                for (int j = 0; j < matrix.column; j++)
                    arrInt[j] = matrix.element[i, j].ToString();
                // rows.Add(arrInt);
                this.dgvMatrix.Rows.Add(arrInt);
            }
        }

        // Kết nối với server
        private void btnConnect_Click(object sender, EventArgs e)
        {

                connect = new ConnectionClient(tbIP.Text);
                lbStatus.ForeColor = Color.OrangeRed;
                lbStatus.Text = "Kết nối với máy chủ thành công!";
                timer1.Enabled = false;
                timer2.Enabled = true;
                btnConnect.Enabled = false;
                tbIP.Enabled = false;
            // Thiết lập các event cho Hàm WaitAndSee và UpdateStatusConnectError
                connect.ProcessReceive += new ConnectionClient.DoSomeThingDelegate(WaitAndReceive);
                connect.UpdateStatusConnect += new ConnectionClient.DoSomeThingDelegate(UpdateStatusConnectFail);
               
           
        }
        // Khi connect fail, ta setup lại các label,timer và textbox
        public void UpdateStatusConnectFail()
        {
             if (InvokeRequired)
                {
                    Invoke(new InvokeSomeMethod(UpdateStatusConnectFail));
                    return;
                }
            lbStatus.Text = "";
            timer1.Enabled = true;
            timer2.Enabled = false;
            btnConnect.Enabled = true;
            tbIP.Enabled = true;
        }
        // Hàm WaitAndReceive được gọi sau khi quá trình gửi dữ liệu và server hoàn tất
        public void WaitAndReceive()
        {
            // kiểm tra lỗi cross thread
                if (InvokeRequired)
                {
                    Invoke(new InvokeSomeMethod(WaitAndReceive));
                    return;
                }
                //MessageBox.Show(connect.HeaderMessage);
                //MessageBox.Show(connect.ReceiveMessage);

            // header = 0 => server gửi ma trận, xử lý ma trận và thoát
                if (connect.HeaderMessage == "0")
                {
                    PopulateMatrix();
                    timer2.Enabled = false;
                    //MessageBox.Show("Ma trận đã được nhận!");
                    lbStatus.ForeColor = Color.Blue;
                    lbStatus.Text = "Sẵn sàng nhận thông báo từ server...";
                    // kết thúc, ta gửi về 0 để báo đã nhận được thông điệp
                    connect.SendData("0");
                    return;
                }
            // Nếu không phải gửi ma trận thì đó là thông điệp, ta tiến hành xử lý
                ArrayList arraylist = new ArrayList();
                string e = string.Empty;
                string v = connect.ReceiveMessage; // Đây là chuỗi v nhận được
                // Chuoi nhan duoc
                arraylist.Add(v);

                // Nếu ma trận sinh tạo ma trận kiểm tra có số cột trùng nhau 
                // hoặc ma tâận sinh có khoảng cách hamming <= 2 thì
                // ta không sửa lỗi được, ta chỉ kiểm tra sai, nếu có sai yêu cầu gửi lại, nếu dúng ta giải mã
                if (matrix.DistanceHamming <=2 || matrix.testingMatrixColumnPosition.Keys.Count < matrix.column) 
                {
                    try
                    {
                        if (matrix.DistanceHamming <= 1)
                        {
                            arraylist.Add("Không tính syndrome");
                            arraylist.AddRange(new string[] { "Không xác định", " ", " ", " " });
                            Matrix receiveMatrix = new Matrix(connect.ReceiveMessage); // tao ma tran nhan duoc
                            arraylist.Add(matrix.decrypt(receiveMatrix).ToString());
                            connect.SendData("0"); //Không lỗi ta gửi 0 cho server
                        }
                        if (matrix.DistanceHamming == 2 || matrix.testingMatrixColumnPosition.Keys.Count < matrix.column)
                        {
                            Matrix transposeTestingMatrix = TestingMatrix.Transpose(); // tao ma tran kiem tra nghich dao
                            Matrix receiveMatrix = new Matrix(connect.ReceiveMessage); // tao ma tran nhan duoc
                            Matrix syndrome = receiveMatrix.Multiply(transposeTestingMatrix); // ket qua nhan ma tran kiem tra
                            // syndrome
                            arraylist.Add(syndrome.ToString());

                            //Nếu syndrome không = vector 0, và nằm trong ma trận kiểm tra thì loi
                            if (!syndrome.IsZero && matrix.testingMatrixColumnPosition.ContainsKey(syndrome.ToString())) // Trường hợp có lỗi
                            {
                                arraylist.Add("Error");
                                arraylist.AddRange(new string[] { "Không có vector lỗi", " ", "Không thể sửa !" });
                                arraylist.Add("Có lỗi,đã yêu cầu gửi lại");
                                connect.SendData("1"); //Lỗi, send 1 yêu cầu gửi lại
                            }
                            else
                            {
                                arraylist.Add("OK");
                                arraylist.AddRange(new string[] { "Không có vector lỗi", " ", "Không thể sửa !" });
                                arraylist.Add(matrix.decrypt(receiveMatrix).ToString());
                                connect.SendData("0"); //Không lỗi ta gửi 0 cho server
                            }

                        }

                    }
                    catch
                    {
                        MessageBox.Show("Có lỗi trong quá trình xử lý từ mã khi ma trận kiểm tra có cột bị trùng");
                    }
                }

                else{ // ngược lại, tiến hành kiểm tra lỗi và sửa lỗi.
                    Matrix transposeTestingMatrix = TestingMatrix.Transpose(); // tao ma tran kiem tra nghich dao
                    Matrix ReceiveMatrix = new Matrix(connect.ReceiveMessage); // tao ma tran nhan duoc
                    Matrix syndrome = ReceiveMatrix.Multiply(transposeTestingMatrix); // ket qua nhan ma tran kiem tra
                    // syndrome
                    arraylist.Add(syndrome.ToString());

                    //Nếu syndrome = vector 0 thì không lỗi
                    if (syndrome.IsZero) // Trường hợp không lỗi
                    {
                        arraylist.Add("OK");
                        arraylist.AddRange(new string[] { " ", " ", " " });
                        arraylist.Add(matrix.decrypt(ReceiveMatrix).ToString());
                        connect.SendData("0"); //Không lỗi ta gửi 0 cho server
                    }
                    else //Trường hợp syndrome khác vector 0 thì
                        // kiểm tra coi có trong bảng chứa các cột của ma trận kiểm tra không
                        // Nếu có nghĩa là có lỗi và sửa sai thử.
                        // Nếu không có, gửi server giá trị 1 để báo gửi lại
                        if (matrix.testingMatrixColumnPosition.ContainsKey(syndrome.ToString()))
                        {
                            arraylist.Add("Error");
                            int ePosition = (int)matrix.testingMatrixColumnPosition[syndrome.ToString()];
                            //arraylist.Add(ePosition.ToString()); // vi tri sai
                            for (int i = 1; i <= matrix.column; i++)
                                e += (ePosition == i) ? "1" : "0";
                            arraylist.Add(e); // vector e
                            Matrix eMatrix = new Matrix(e);
                            // Sau khi sua lai  
                            ReceiveMatrix = eMatrix.Addition(ReceiveMatrix); // w=v+e
                            arraylist.Add(ReceiveMatrix.ToString()); // them vao w sau khi sua
                            // thu lai
                            syndrome = ReceiveMatrix.Multiply(TestingMatrix.Transpose());
                            // if (matrix.testingMatrixColumnPosition.ContainsKey(syndrome.ToString())).i
                            if (!syndrome.IsZero)
                            {
                                arraylist.Add("FAIL");
                                connect.SendData("1"); // error send 1
                            }
                            else
                            {
                                arraylist.Add("SUCCESS");
                                arraylist.Add(matrix.decrypt(ReceiveMatrix).ToString()); // thong diep gui la
                                connect.SendData("0"); // succes send 0
                            }
                        }
                        else // từ mã gửi sai không thể sửa lại
                        {
                            MessageBox.Show("Không thể sửa, Click Ok để gửi lại");
                            arraylist.AddRange(new string[] { "Error", " ", " ", "Không thể sửa !", "Không xác định !" });
                            connect.SendData("1");// gửi 1, lỗi
                        }

                }
                // Add vao list view
                string[] String_result = (string[])arraylist.ToArray(typeof(string));
                FillInfoFromArray(String_result);
        }


        // Điền các thông số và các textbox tương ứng
        private void FillInfoFromArray(string[] array)
        {
            for (int i = 0; i < array.Length; i++)
            {
                tbV.Text = array[0];
                tbSv.Text = array[1];
                tbStatus1.Text = array[2];
                tbE.Text = array[3];
                tbW.Text = array[4];
                tbStatus2.Text = array[5];
                tbU.Text = array[6];
            }
        }

        // sự kiện load form
        private void FormReceive_Load(object sender, EventArgs e)
        {
            timer1.Enabled=true;
            MaximizeBox = false;
        }

        private void timer1_Tick_1(object sender, EventArgs e)
        {
            lbStatus.ForeColor = Color.Red ;
            if (lbStatus.Text != "") lbStatus.Text = "";
            else lbStatus.Text = "Chưa kết nối với máy chủ!";
        }

        private void timer2_Tick(object sender, EventArgs e)
        {
            if (lbStatus.Text == "Kết nối với máy chủ thành công!") lbStatus.Text = "Đang chờ nhận ma trận sinh...";
            else lbStatus.Text = "Kết nối với máy chủ thành công!";
        }

        private void btnGenMatrix_Click(object sender, EventArgs e)
        {
            if (matrix != null)
            {
                SetupDataGridView(matrix);
            }
            else
            {
                MessageBox.Show("Chưa nhận được ma trận sinh!");
            }
        }

        private void btnChkMatrix_Click(object sender, EventArgs e)
        {
            if (matrix != null)
            {
                SetupDataGridView(TestingMatrix);
            }
            else
            {
                MessageBox.Show("Chưa có ma trận kiểm tra!");
            }
        }


    }
}